package hibatis.support.parse;

import hibatis.support.Reflection;
import hibatis.support.generator.FromAndWhereGenerator;
import hibatis.support.generator.SelectGenerator;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;

/**
 * Created by huangdachao on 2018/6/23 00:18.
 */
public class HasManayStatementParser {
    private static final Logger LOG = LoggerFactory.getLogger(HasManayStatementParser.class);

    public static MappedStatement generate(Configuration conf, Field field) {
        FromAndWhereGenerator faw = new FromAndWhereGenerator(field);

        // select ... from ...
        StringBuilder sql = new StringBuilder("<script>select ");
        sql.append(SelectGenerator.generateSelectColumnList(faw.getViewMeta(), faw.getTableAliasMap()));
        sql.append(faw.generate());
        sql.append(faw.getPageAndSort().toSql(faw.getTableAliasMap()));
        sql.append("</script>");
        LOG.debug(sql.toString());
        LanguageDriver languageDriver = conf.getLanguageRegistry().getDriver(XMLLanguageDriver.class);
        SqlSource sqlSource = languageDriver.createSqlSource(conf, sql.toString(), field.getDeclaringClass());

        Integer fetchSize = null;
        Integer timeout = null;
        StatementType statementType = StatementType.PREPARED;
        ResultSetType resultSetType = ResultSetType.FORWARD_ONLY;
        SqlCommandType sqlCommandType = SqlCommandType.SELECT;
        boolean flushCache = false;
        boolean useCache = true;
        KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
        String keyProperty = null;
        String keyColumn = null;

        String resultMapId = Reflection.formatField(field);
        MapperBuilderAssistant assistant = new MapperBuilderAssistant(conf, resultMapId);
        assistant.setCurrentNamespace(field.getDeclaringClass().getName());
        assistant.addResultMap(resultMapId, faw.getEntityMeta().getEntityClass(), null, null, new ArrayList<>(), null);
        final String mappedStatementId = resultMapId;
        return assistant.addMappedStatement(
            mappedStatementId,
            sqlSource,
            statementType,
            sqlCommandType,
            fetchSize,
            timeout,
            // ParameterMapID
            null,
            field.getDeclaringClass(),
            resultMapId,
            faw.getEntityMeta().getEntityClass(),
            resultSetType,
            flushCache,
            useCache,
            false,
            keyGenerator,
            keyProperty,
            keyColumn,
            // DatabaseID
            null,
            languageDriver,
            // ResultSets
            null);
    }
}
